#include "config.h"
#include "js-engine.h"
#include "desktop-element.h"
#include "mainview-parser.h"
#include "misc.h"

#include <glib.h>
#include <glib/gstdio.h>
#include <glib/gi18n.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define FAILED 1
static gboolean isInteractive = FALSE;
static gchar **package_dir = NULL;
static GOptionEntry options[] = {
    {"interactive", 'i', 0, G_OPTION_ARG_NONE, &isInteractive, N_("JavaScript interactive mode"), NULL},
    { NULL }
};

gboolean interactive_loop(js_engine *engine)
{
    GError *err = NULL;
    GIOChannel *in;
    g_return_val_if_fail(stdin, FALSE);
    in = g_io_channel_unix_new(STDIN_FILENO);
    while(1){
	GString *buffer = g_string_new(NULL);
	gchar *return_message;
	jsval rval;
	JSBool result;
	g_fprintf(stderr, "%s","eval> ");
	g_io_channel_read_line_string(in, buffer, NULL, &err);
	if(buffer->len > 0){
	    result = JS_EvaluateScript(engine->cx, engine->view, buffer->str, buffer->len, NULL, 0, &rval);
	    if(rval != JSVAL_VOID){
		return_message = JS_GetStringBytes(JS_ValueToString(engine->cx, rval));
		g_fprintf(stderr, "%s\n",return_message);
	    }
	    if(result == JS_FALSE){
  	        g_warning("eval failed.");
	    }
	}
	g_string_free(buffer, TRUE);
    }
    g_io_channel_close(in);
    return TRUE;
}

static gboolean expose(GtkWidget *widget, GdkEventExpose *event, gpointer userdata) {
    cairo_t *cr = gdk_cairo_create(widget->window);

    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0);
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
    cairo_paint(cr);
    cairo_destroy(cr);
    return FALSE;
}

static void screen_changed(GtkWidget *widget, GdkScreen *old_screen, gpointer userdata) {
    GdkScreen *screen = gtk_widget_get_screen(widget);
    GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen);
    gtk_widget_set_colormap(widget, colormap);
}

gboolean window_button_release_cb(GtkWidget *widget, GdkEventButton *event, gpointer ptr)
{
    GtkWidget *menu = (GtkWidget *)ptr;
    g_return_val_if_fail(ptr, FALSE);
    if(event->button == 3){
	gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, 0);
    }
    return FALSE;
}

int main(int argc, char **argv, char **envp) {
    GOptionContext *optionCx;
    gint window_width = -1, window_height = -1;
    jsval rval;
    desktop_element *root_view = NULL;
    js_engine *engine = NULL;
    GtkWidget *window = NULL;
    GtkWidget *menu = NULL;
    GHashTable *manifestTable = NULL;
    GThread *interactive;
    GError *err = NULL;

    bindtextdomain(GETTEXT_PACKAGE,COMONOLOCALEDIR);
    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
    textdomain (GETTEXT_PACKAGE);

    g_thread_init(NULL);
    gtk_init(&argc, &argv);
    optionCx = g_option_context_new("[Gadget package directory] - Google Desktop Gadget interpreter for Free Desktop System");
    g_option_context_add_main_entries(optionCx, options, GETTEXT_PACKAGE);
    g_option_context_parse(optionCx, &argc, &argv, &err);

    engine = js_engine_new();

    if (!engine){
        g_error(_("JavaScript Engine Initialize Error"));
	exit(FAILED);
    }

    if (argc > 1) {
        gint result = g_chdir(argv[1]);
	if(result){
	    g_warning(_("Cannot access %s: No such directory."), argv[1]);
	    exit(FAILED);
	}
    }

    root_view = mainview_parse(engine);
    if(root_view == NULL){
	g_warning(_("Failed to parse main.xml."));
	exit(FAILED);
    }
    mainview_set_js_object(engine, root_view);

    manifestTable = load_gmanifest_xml(engine);
    if(manifestTable == NULL){
	g_warning(_("Cannot access gadget.gmanifest."));
    }

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_app_paintable(window, TRUE);
    gtk_window_set_decorated(GTK_WINDOW(window), FALSE);

    JS_GetProperty(engine->cx, root_view->jsobj, "width", &rval);

    if(JSVAL_IS_INT(rval))
        window_width = JSVAL_TO_INT(rval);

    JS_GetProperty(engine->cx, root_view->jsobj, "height", &rval);
    if(JSVAL_IS_INT(rval))
	window_height = JSVAL_TO_INT(rval);
    gtk_widget_set_size_request(window, window_width, window_height);
    
    g_signal_connect(window, "expose-event", G_CALLBACK(expose), NULL);
    g_signal_connect(window, "screen-changed", G_CALLBACK(screen_changed), NULL);
    screen_changed(window, NULL, NULL);
    menu = context_menu_new(GTK_WINDOW(window), manifestTable, engine);

    desktop_element_set_view(engine, root_view);
    desktop_element_set_position(root_view, root_view->children);
    gtk_widget_set_events(window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
    g_signal_connect(window, "button-release-event", window_button_release_cb, menu);
    gtk_container_add(GTK_CONTAINER(window), root_view->view);

    if(isInteractive){
	interactive = g_thread_create(interactive_loop, engine, FALSE, &err);
    }
    gtk_widget_show(window);
    desktop_element_call_handler(root_view, "onopen");
    g_option_context_free(optionCx);
    gtk_main();
    return 0;
}
